﻿using AiMoWindows.CodeScripts;
using AiMoWindows.CodeScripts.Analysis;
using AiMoWindows.Localization;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
namespace AiMoWindows.MainActions.ScriptActions.SubActions
{
    class SyncScriptsAction(ActionsController actions, ScriptManager scriptManager)
    {
        readonly ActionsController actions = actions;
        readonly ScriptManager scriptManager = scriptManager;
        bool needUpdateReference = false;
        public MetadataReference[] GetUpdatedAllMetadataReference()
        {
            if (scriptManager.ExternalReferencesLocations.Length == 0)
            {
                actions.Printer.PrintDebug(Local.Get("No external reference."));
            }
            else
            {
                actions.Printer.PrintDebug(Local.Get("Updated external reference:") + "\r\n    " + string.Join("\r\n    ", scriptManager.ExternalReferencesLocations));
            }
            return scriptManager.AllReferences;
        }
        /// <summary>
        /// 从AiMo的后台，获取新的文字，并且把变化同步给现在的Document，以支持undo
        /// </summary>
        /// <returns></returns>
        public async Task<SourceText> GetChangedDocumentFromAiMoScriptManager()
        {
            Document document = actions.CurrentDocument;
            SourceText originalText = await document.GetTextAsync();
            SourceText newText = SourceText.From(scriptManager.CurrentCodeText());
            Document newDocument = document.WithText(newText);
            var changes = await newDocument.GetTextChangesAsync(document);
            return originalText.WithChanges(changes);
        }
        /// <summary>
        /// 三个引用，两个是手动添加Loop和OnLoad
        /// 剩下则是在 SyncScriptsWithFormat Sync代码的时候
        /// </summary>
        public async Task<bool> SendEditorScriptToBack()
        {
            //System.Diagnostics.Debug.WriteLine("SendToBack start");
            Document document = actions.CurrentDocument;
            document = await actions.FormatAction.FormatDocumentAsync(document);
            SyntaxNode? root = await document.GetSyntaxRootAsync();
            SyntaxConvertResult result = SyntaxConverter.ConvertDocumentToAiMoScriptSource(root);
            if (!result.Result)
            {
                actions.Printer.PrintDebug(Local.Get("Code Sync Error:") + "\r\n" + result.PrintInformation);
                return false;
            }
            else if (!string.IsNullOrEmpty(result.PrintInformation))
            {
                actions.Printer.PrintDebug(result.PrintInformation);
            }
            scriptManager.SyncModifyToScript(result, out bool referenceDirectiveChanged);
            needUpdateReference = referenceDirectiveChanged;
            //System.Diagnostics.Debug.WriteLine("SendToBack end");
            return true;
        }
        public async Task BringBackScriptToEditor()
        {
            if (actions.HasState(SyncScriptState.InBringBackToEditor)) return;
            actions.AddState(SyncScriptState.InBringBackToEditor);
            //System.Diagnostics.Debug.WriteLine("BringBackToEditor start");
            // 这个方法对应 RoslynPad.UI.OpenDocumentViewModel 中的 void OnRestoreCompleted(RestoreResult restoreResult)
            Document document = actions.CurrentDocument;
            if (needUpdateReference)
            {
                var project = document.Project;
                project = project.WithMetadataReferences(GetUpdatedAllMetadataReference());
                document = project.GetDocument(actions.DocumentId)!;
            }
            SourceText newText = await GetChangedDocumentFromAiMoScriptManager();
            actions.ScriptsHost.UpdateDocument(document.WithText(newText));
            actions.Editor.RefreshHighlighting();
            actions.RemoveState(SyncScriptState.InBringBackToEditor);
            //System.Diagnostics.Debug.WriteLine("BringBackToEditor end");
        }
        /// <summary>
        /// Format代码，并且同步
        /// 1. Initialize 的时候： ScriptWindow.InitializeEditor() 》 actions.Initialize 》 this
        /// 2. 
        /// </summary>
        public async Task<bool> SyncScriptsWithFormat()
        {
            // 已经Sync的时候，就不重复Sync了
            if (actions.HasState(SyncScriptState.InSyncWithFormatScripts)) return false;
            actions.AddState(SyncScriptState.InSyncWithFormatScripts);
            //System.Diagnostics.Debug.WriteLine("SyncScriptsWithFormat() start");
            bool re = await SendEditorScriptToBack();
            if (re)
            {
                await BringBackScriptToEditor();
            }
            actions.RemoveState(SyncScriptState.InSyncWithFormatScripts);
            //System.Diagnostics.Debug.WriteLine("SyncScriptsWithFormat() end"); 
            return re;
        }
    }
}
